Setup

Install a package countrycode first.

library(tidyverse)
library(WDI)
library(readxl)
library(countrycode)

World Inequality Database

https://wid.world

World Inequality Report 2022

Since Excel files are binary file, you need to add mode = “wb”, web binary.

url_summary <- "https://wir2022.wid.world/www-site/uploads/2022/03/WIR2022TablesFigures-Summary.xlsx"
download.file(url = url_summary, destfile = "data/WIR2022s.xlsx", mode = "wb")
trying URL 'https://wir2022.wid.world/www-site/uploads/2022/03/WIR2022TablesFigures-Summary.xlsx'
Content type 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet' length 908659 bytes (887 KB)
==================================================
downloaded 887 KB
library(readxl) # readxl is a part of tidyverse but not a core package
excel_sheets("data/WIR2022s.xlsx")
 [1] "Index"     "F1"        "F2"        "F3"        "F4"        "F5."       "F6"       
 [8] "F7"        "F8"        "F9"        "F10"       "F11"       "F12"       "F13"      
[15] "F14"       "F15"       "T1"        "data-F1"   "data-F2"   "data-F3"   "data-F4"  
[22] "data-F5"   "data-F6"   "data-F7"   "data-F8"   "data-F9"   "data-F10"  "data-F11" 
[29] "data-F12"  "data-F13." "data-F14." "data-F15" 
df_wir_f2 <- read_excel("data/WIR2022s.xlsx", 
    sheet = "data-F2")
df_wir_f2

Created a new Excel book with only one sheet, and save it as a CSV UTF-8.

df_wir_f2_2 <- read_csv("data/wir-f2.csv")
Rows: 8 Columns: 5── Column specification ─────────────────────────────────────────────────────────────────
Delimiter: ","
chr (4): iso, Bottom 50%, Middle 40%, Top 10%
dbl (1): year
ℹ Use `spec()` to retrieve the full column specification for this data.
ℹ Specify the column types or set `show_col_types = FALSE` to quiet this message.
df_wir_f2_2
df_wir_f2_2 |> identical(df_wir_f2)
[1] FALSE
df_wir_f2_3 <- read_delim(clipboard())
df_wir_f2_3
df_wir_f2 |> pivot_longer(3:5) |> 
  ggplot(aes(iso, value, fill = name)) + geom_col(position = "dodge") + coord_flip()

See: https://ds-sl.github.io/data-analysis/wir2022.nb.html

To share data with someone else.

dput(df_wir_f2)
structure(list(year = c(2021, 2021, 2021, 2021, 2021, 2021, 2021, 
2021), iso = c("Europe", "East Asia", "North America", "Russia & Central Asia", 
"South & South East Asia", "Latin America", "Sub-Saharan Africa", 
"MENA"), `Bottom 50%` = c(0.1891, 0.1391, 0.1322, 0.1466, 0.1233, 
0.1016, 0.0892, 0.09), `Middle 40%` = c(0.4531, 0.4268, 0.4105, 
0.3863, 0.3283, 0.3445, 0.3537, 0.3288), `Top 10%` = c(0.3578, 
0.4341, 0.4573, 0.4671, 0.5484, 0.5539, 0.5571, 0.5812)), class = c("tbl_df", 
"tbl", "data.frame"), row.names = c(NA, -8L))
df_wir_dput <- dput(df_wir_f2)
structure(list(year = c(2021, 2021, 2021, 2021, 2021, 2021, 2021, 
2021), iso = c("Europe", "East Asia", "North America", "Russia & Central Asia", 
"South & South East Asia", "Latin America", "Sub-Saharan Africa", 
"MENA"), `Bottom 50%` = c(0.1891, 0.1391, 0.1322, 0.1466, 0.1233, 
0.1016, 0.0892, 0.09), `Middle 40%` = c(0.4531, 0.4268, 0.4105, 
0.3863, 0.3283, 0.3445, 0.3537, 0.3288), `Top 10%` = c(0.3578, 
0.4341, 0.4573, 0.4671, 0.5484, 0.5539, 0.5571, 0.5812)), class = c("tbl_df", 
"tbl", "data.frame"), row.names = c(NA, -8L))
df_wir_dput
df_wir_f2_3 <- df_wir_dput
df_wir_f2_3 |> identical(df_wir_f2)
[1] TRUE

UNdata - a world of information

https://data.un.org/

Popular statistical tables

Explorer - datamarts: http://data.un.org/Explorer.aspx

UN Migrants Data

url_un_migrants <- "https://data.un.org/_Docs/SYB/CSV/SYB66_327_202310_International%20Migrants%20and%20Refugees.csv"

Since the url is given, a CSV file can be read directly using read_csv.

df_un_migrants <- read_csv(url_un_migrants, skip = 1)
New names:Rows: 7238 Columns: 7── Column specification ─────────────────────────────────────────────────────────────────
Delimiter: ","
chr (4): ...2, Series, Footnotes, Source
dbl (2): Region/Country/Area, Year
num (1): Value
ℹ Use `spec()` to retrieve the full column specification for this data.
ℹ Specify the column types or set `show_col_types = FALSE` to quiet this message.
df_un_migrants
str(df_un_migrants)
spc_tbl_ [7,238 × 7] (S3: spec_tbl_df/tbl_df/tbl/data.frame)
 $ Region/Country/Area: num [1:7238] 1 1 1 1 1 1 1 1 1 1 ...
 $ ...2               : chr [1:7238] "Total, all countries or areas" "Total, all countries or areas" "Total, all countries or areas" "Total, all countries or areas" ...
 $ Year               : num [1:7238] 2005 2005 2005 2005 2010 ...
 $ Series             : chr [1:7238] "International migrant stock: Both sexes (number)" "International migrant stock: Both sexes (% total population)" "International migrant stock: Male (% total Population)" "International migrant stock: Female (% total Population)" ...
 $ Value              : num [1:7238] 1.91e+08 2.90 3.00 2.90 2.21e+08 ...
 $ Footnotes          : chr [1:7238] NA NA NA NA ...
 $ Source             : chr [1:7238] "United Nations Population Division, New York, International migrant stock: The 2020 Revision, last accessed January 2022." "United Nations Population Division, New York, International migrant stock: The 2020 Revision, last accessed January 2022." "United Nations Population Division, New York, International migrant stock: The 2020 Revision, last accessed January 2022." "United Nations Population Division, New York, International migrant stock: The 2020 Revision, last accessed January 2022." ...
 - attr(*, "spec")=
  .. cols(
  ..   `Region/Country/Area` = col_double(),
  ..   ...2 = col_character(),
  ..   Year = col_double(),
  ..   Series = col_character(),
  ..   Value = col_number(),
  ..   Footnotes = col_character(),
  ..   Source = col_character()
  .. )
 - attr(*, "problems")=<externalptr> 
df_un_migrants |> summary()
 Region/Country/Area     ...2                Year         Series         
 Min.   :  1.0       Length:7238        Min.   :2005   Length:7238       
 1st Qu.:178.0       Class :character   1st Qu.:2010   Class :character  
 Median :404.0       Mode  :character   Median :2015   Mode  :character  
 Mean   :407.1                          Mean   :2014                     
 3rd Qu.:630.0                          3rd Qu.:2020                     
 Max.   :894.0                          Max.   :2022                     
     Value            Footnotes            Source         
 Min.   :        0   Length:7238        Length:7238       
 1st Qu.:        5   Class :character   Class :character  
 Median :      154   Mode  :character   Mode  :character  
 Mean   :   731059                                        
 3rd Qu.:    31096                                        
 Max.   :280598105                                        
df_un_migrants |> select(Year,Series) |> lapply(unique)
$Year
 [1] 2005 2010 2015 2020 2022 2019 2018 2016 2021 2017

$Series
[1] "International migrant stock: Both sexes (number)"             
[2] "International migrant stock: Both sexes (% total population)" 
[3] "International migrant stock: Male (% total Population)"       
[4] "International migrant stock: Female (% total Population)"     
[5] "Total refugees and people in refugee-like situations (number)"
[6] "Asylum seekers, including pending cases (number)"             
[7] "Other of concern to UNHCR (number)"                           
[8] "Total population of concern to UNHCR (number)"                
df_un_migrants |> distinct(`Region/Country/Area`, ...2)
library(countrycode)
df_un_migrants %>% mutate(iso2c_un = countrycode(`Region/Country/Area`, "un", "iso2c"), .after = ...2)
Warning: There was 1 warning in `mutate()`.
ℹ In argument: `iso2c_un = countrycode(`Region/Country/Area`, "un", "iso2c")`.
Caused by warning:
! Some values were not matched unambiguously: 1, 2, 5, 9, 11, 13, 14, 15, 17, 18, 21, 29, 30, 34, 35, 39, 53, 54, 57, 61, 62, 142, 143, 145, 150, 151, 154, 155, 202, 419, 420, 830
df_un_migrants |> mutate(iso2c_un = countrycode(`Region/Country/Area`, "un", "iso2c"), .after = ...2) |> filter(is.na(iso2c_un)) |> distinct(...2)
Warning: There was 1 warning in `mutate()`.
ℹ In argument: `iso2c_un = countrycode(`Region/Country/Area`, "un", "iso2c")`.
Caused by warning:
! Some values were not matched unambiguously: 1, 2, 5, 9, 11, 13, 14, 15, 17, 18, 21, 29, 30, 34, 35, 39, 53, 54, 57, 61, 62, 142, 143, 145, 150, 151, 154, 155, 202, 419, 420, 830
wdicache <- read_rds("data/wdicache.rds")
wdi_country_extra <- wdicache$country |> select(iso2c, region, income, lending)
df_un_migrants_ext <- df_un_migrants %>% 
  mutate(iso2c_un = countrycode(`Region/Country/Area`, "un", "iso2c"), .after = ...2) |>
  drop_na(iso2c_un) |> 
  select(Country = ...2, ISO2C = iso2c_un, Year, Series, Value, Footnotes) |>
  left_join(wdi_country_extra, by = c("ISO2C" = "iso2c"))
df_un_migrants_ext
Warning: There was 1 warning in `mutate()`.
ℹ In argument: `iso2c_un = countrycode(`Region/Country/Area`, "un", "iso2c")`.
Caused by warning:
! Some values were not matched unambiguously: 1, 2, 5, 9, 11, 13, 14, 15, 17, 18, 21, 29, 30, 34, 35, 39, 53, 54, 57, 61, 62, 142, 143, 145, 150, 151, 154, 155, 202, 419, 420, 830
df_un_migrants_ext$Series |> unique()
[1] "International migrant stock: Both sexes (number)"             
[2] "International migrant stock: Both sexes (% total population)" 
[3] "International migrant stock: Male (% total Population)"       
[4] "International migrant stock: Female (% total Population)"     
[5] "Total refugees and people in refugee-like situations (number)"
[6] "Asylum seekers, including pending cases (number)"             
[7] "Other of concern to UNHCR (number)"                           
[8] "Total population of concern to UNHCR (number)"                
df_un_migrants_ext_rev <- df_un_migrants_ext |> mutate(Ser = case_when(
  Series == "International migrant stock: Both sexes (number)" ~ "migrant",
  Series == "International migrant stock: Both sexes (% total population)" ~ "migrant_percent",
  Series == "International migrant stock: Male (% total Population)" ~ "migrant_male",
  Series == "International migrant stock: Female (% total Population)" ~ "migrant_female",
  Series == "Total refugees and people in refugee-like situations (number)" ~ "refugee",
  Series == "Asylum seekers, including pending cases (number)" ~ "asylum",
  Series == "Other of concern to UNHCR (number)"  ~ "other",
  Series == "Total population of concern to UNHCR (number)" ~ "concern",
  TRUE ~ Series), .before = Series)
df_un_migrants_ext_rev
dput(df_un_migrants_ext_rev)

Explorer - datamarts

Environment Statistics Database>Water>Internal flow [Link]

Select columns to add Table ID and Country and Area Code of UN, and download ‘Comma’ a CSV.

df_un_water <- read_csv("data/UNdata_Export_20240124_010609671.csv")
Warning: One or more parsing issues, call `problems()` on your data frame for details, e.g.:
  dat <- vroom(...)
  problems(dat)Rows: 1604 Columns: 7── Column specification ─────────────────────────────────────────────────────────────────
Delimiter: ","
chr (3): Country or Area Code, Country or Area, Unit
dbl (4): Table ID, Year, Value, Value Footnotes
ℹ Use `spec()` to retrieve the full column specification for this data.
ℹ Specify the column types or set `show_col_types = FALSE` to quiet this message.
df_un_water

OECD data

OECD data top

OECD data https://data.oecd.org/

  • Browse by Topics (Choose from 12 topics) or Country (Choose from 37 countries)
  • Topics:
    • Agriculture,
    • Development,
    • Economy,
    • Education,
    • Energy,
    • Environment,
    • Finance,
    • Government,
    • Health,
    • Innovation and Technology,
    • Jobs,
    • Society
      • Demography
      • Inequality
      • Migration
      • Population by Region
      • Social protection
  • Countries:
    • Australia, Austria, Belgium, Brazil, Canada, Chili, People’s Republic of China, Columbia, Costa Rica, Czechia, Denmark, Estonia, Finland, France, Germany, Greece, Hungary, Iceland, India, Indonesia, Ireland, Islael, Italy, Japan, Korea, Latvia, Lithuania, Luxembourg, Mexico, Netherlands, New Zealand, Norway, Poland, Portugal, Russian Federation, Slovak Republic, Slovenia, South Africa, Spain, Sweden, Swizerland, Türkiye, United Kingdom, United States

Database Access: https://data-explorer.oecd.org/

There is a newly developed Database Access linked above. However, it is still under development and difficult to handle data there.

Topic: Society - Migration

  • Permanent immigrant inflows
    • Permanent immigrant inflows cover regulated movements of foreigners considered to be settling in the country from the perspective of the destination country. They cover regulated movements of foreigners as well as free movement migration. The data presented are the result of a standardisation process that allows for cross-country comparisons. This indicator is measured by numbers of permanent inflows.
  • Stocks of foreign-born population in OECD countries
  • Foreign-born population
  • Foreign population
  • Native-born employment
  • Foreign-born employment
  • Native-born unemployment
  • Foreign-born unemployment
  • Native-born participation rates
  • Foreign-born participation rates

Permanent immigrant inflows

Permanent immigrant inflows Total, Number, 2022 Link

Definition of Permanent immigrant inflows

  • Permanent immigrant inflows cover regulated movements of foreigners considered to be settling in the country from the perspective of the destination country. They cover regulated movements of foreigners as well as free movement migration. The data presented are the result of a standardisation process that allows for cross-country comparisons. This indicator is measured by numbers of permanent inflows.
  • Citation: OECD (2024), Permanent immigrant inflows (indicator). doi: 10.1787/304546b6-en (Accessed on 27 January 2024)
library(htmltools)

iframe_code <- '<iframe src="https://data.oecd.org/chart/7kgk" width="860" height="645" style="border: 0" mozallowfullscreen="true" webkitallowfullscreen="true" allowfullscreen="true"><a href="https://data.oecd.org/chart/7kgk" target="_blank">OECD Chart: Permanent immigrant inflows, Total, Number, Annual, 2022</a></iframe>'

HTML(iframe_code)

OECD: Permanent immigrant inflows

Data Information

  • Data Site: https://data.oecd.org/migration/permanent-immigrant-inflows.htm

  • Definition of Permanent immigrant inflows: Permanent immigrant inflows cover regulated movements of foreigners considered to be settling in the country from the perspective of the destination country. They cover regulated movements of foreigners as well as free movement migration. The data presented are the result of a standardisation process that allows for cross-country comparisons. This indicator is measured by numbers of permanent inflows.

  • Citation: OECD (2024), Permanent immigrant inflows (indicator). doi: 10.1787/304546b6-en (Accessed on 28 January 2024)

  • Categories: Total, Work, Free movements, Family, Family accompanying workers, Humanitarian, Other

library(tidyverse)
── Attaching core tidyverse packages ───────────────────────────────── tidyverse 2.0.0 ──
✔ dplyr     1.1.4     ✔ readr     2.1.5
✔ forcats   1.0.0     ✔ stringr   1.5.1
✔ ggplot2   3.4.4     ✔ tibble    3.2.1
✔ lubridate 1.9.3     ✔ tidyr     1.3.0
✔ purrr     1.0.2     ── Conflicts ─────────────────────────────────────────────────── tidyverse_conflicts() ──
✖ dplyr::filter() masks stats::filter()
✖ dplyr::lag()    masks stats::lag()
ℹ Use the ]8;;http://conflicted.r-lib.org/conflicted package]8;; to force all conflicts to become errors

Read the downloaded full data of ‘Permanent Immigrant Inflows’.

df_inflows <- read_csv("data/DP_LIVE_28012024004117279.csv")
Rows: 3597 Columns: 8── Column specification ─────────────────────────────────────────────────────────────────
Delimiter: ","
chr (5): LOCATION, INDICATOR, SUBJECT, MEASURE, FREQUENCY
dbl (2): TIME, Value
lgl (1): Flag Codes
ℹ Use `spec()` to retrieve the full column specification for this data.
ℹ Specify the column types or set `show_col_types = FALSE` to quiet this message.
df_inflows
df_inflows |> select(-Value) |> lapply(unique)
$LOCATION
 [1] "AUS" "AUT" "BEL" "CAN" "DNK" "FIN" "FRA" "DEU" "IRL" "ITA" "JPN" "KOR" "NLD" "NZL"
[15] "NOR" "PRT" "ESP" "SWE" "CHE" "GBR" "USA" "ISR" "RUS" "MEX" "CZE" "LUX" "POL" "EST"

$INDICATOR
[1] "IMMIGINFLOW"

$SUBJECT
[1] "FAM"      "FAMWORKR" "FREEMOVS" "HUMNTRN"  "OTH"      "WORK"     "TOT"     

$MEASURE
[1] "NBR"

$FREQUENCY
[1] "A"

$TIME
 [1] 2003 2004 2005 2006 2007 2008 2009 2010 2011 2012 2013 2014 2015 2016 2017 2018 2019
[18] 2020 2021 2022 2000 2001 2002 1995 1996 1997 1998 1999

$`Flag Codes`
[1] NA

Set the order of categories to display.

CAT <- c("TOT", "WORK", "FREEMOVS", "FAM", "FAMWORKR", "HUMNTRN", "OTH")

Add country names using the countrycode package and delete INDICATOR, MEASURE, FREQUENCY, Flag Codes.

df_in <- df_inflows |> 
  mutate(country = countrycode(LOCATION, "iso3c", "country.name"), .before = LOCATION) |> 
  select(country, iso3c = LOCATION, category = SUBJECT, year = TIME, value = Value)
df_in
df_in |> filter(country == "Japan") |> 
  ggplot(aes(year, value, col = factor(category, levels = CAT))) + geom_line() + labs(col = "Categories")

df_in |> filter(country == "Japan") |> filter(category != "TOT") |> 
  ggplot(aes(year, value, fill = factor(category, levels = rev(CAT)))) + 
  geom_area(col = "black", linewidth = 0.1) +
  labs(title = "Permanent immigrant inflows of Japan", fill = "Categories")

df_in |> filter(category != "TOT") |> 
  ggplot(aes(year, value, fill = factor(category, levels = rev(CAT)))) + geom_area(col = "black", linewidth = 0.1) +
  facet_wrap(~country) + 
  labs(title = "Permanent immigrant inflows of 28 Countries", fill = "") +
  theme(legend.position = 'bottom')

df_in |> filter(country %in% c("Germany", "United States")) |> 
  ggplot(aes(year, value, col = country, linetype = factor(category, levels = CAT))) + geom_line() +
  labs(title = "Permanent immigrant inflows of Germany and United States", linetype = "Categories")

tot_lev <- df_in |> pivot_wider(names_from = category, values_from = value) |> 
  pivot_longer(cols = CAT[CAT!="TOT"], names_to = "category", values_to = "value") |> filter(year == 2022) |> distinct(country, iso3c, TOT) |> arrange(desc(TOT)) |> pull(country)
df_in |> pivot_wider(names_from = category, values_from = value) |> 
  pivot_longer(cols = CAT[CAT!="TOT"], names_to = "category", values_to = "value") |> filter(year == 2022) |> ggplot(aes(factor(country, levels = rev(tot_lev)), value, fill = factor(category, levels = CAT))) + geom_col(col = "black", linewidth = 0.1) + coord_flip() +
  labs(title = "Permanent immigrant inflows in 2022", fill = "", x = "") +
  theme(legend.position = 'bottom')

OECD: Foreign population

Data Information

  • Data Site: https://data.oecd.org/migration/foreign-population.htm

  • Definition of Foreign population: The foreign population consists of people who still have the nationality of their home country. It may include people born in the host country. The difference across countries between the size of the foreign-born population and that of the foreign population depends on the rules governing the acquisition of citizenship in each country. This indicator is measured as a percentage of population.

  • Citation: OECD (2024), Foreign population (indicator). doi: 10.1787/16a914e3-en (Accessed on 28 January 2024)

  • Categories: Total, Percent of Population

Read the downloaded full data of ‘Foreign population’.

df_foreign <- read_csv("data/DP_LIVE_28012024004200124.csv")
Rows: 545 Columns: 8── Column specification ─────────────────────────────────────────────────────────────────
Delimiter: ","
chr (5): LOCATION, INDICATOR, SUBJECT, MEASURE, FREQUENCY
dbl (2): TIME, Value
lgl (1): Flag Codes
ℹ Use `spec()` to retrieve the full column specification for this data.
ℹ Specify the column types or set `show_col_types = FALSE` to quiet this message.
df_foreign
df_foreign |> select(-Value) |> lapply(unique)
$LOCATION
 [1] "AUT" "BEL" "DNK" "FIN" "DEU" "HUN" "IRL" "ITA" "JPN" "KOR" "LUX" "NLD" "NOR" "PRT"
[15] "SVK" "SWE" "CHE" "GBR" "USA" "SVN" "CZE" "FRA" "POL" "ESP" "GRC" "EST" "ISL" "CAN"
[29] "MEX" "TUR" "CHL" "LVA" "LTU"

$INDICATOR
[1] "FPOP"

$SUBJECT
[1] "TOT"

$MEASURE
[1] "PC_POP"

$FREQUENCY
[1] "A"

$TIME
 [1] 2000 2001 2002 2003 2004 2005 2006 2007 2008 2009 2010 2011 2012 2013 2014 2015 2016
[18] 2017 2018 2019

$`Flag Codes`
[1] NA

Add country names using the countrycode package and delete INDICATOR, MEASURE, FREQUENCY, Flag Codes.

df_fpop <- df_foreign |> 
  mutate(country = countrycode(LOCATION, "iso3c", "country.name"), .before = LOCATION) |> 
  select(country, iso3c = LOCATION, year = TIME, foreign = Value)
df_fpop
df_fpop |> filter(country == "Japan") |> 
  ggplot(aes(year, foreign)) + geom_line() + 
  labs(title = "Foreign Population in Japan (Percent)")

df_fpop |> 
  ggplot(aes(year, foreign)) + geom_line(aes(col = iso3c)) + 
  geom_smooth(formula = 'y~x', method = "loess", se = FALSE) + 
  labs(title = "Total Foreign Population (%)")

df_fpop |> filter(year == 2019) |> 
  ggplot(aes(fct_reorder(country, foreign), foreign)) + geom_col() + 
  coord_flip() + labs(title = "Foreign Population (%)", x = "", y = "")

OECD: PopulationTotal, Million persons, 2022 or latest available

Data Information

  • Data Site: https://data.oecd.org/pop/population.htm

  • Definition of Population: Population is defined as all nationals present in, or temporarily absent from a country, and aliens permanently settled in a country. This indicator shows the number of people that usually live in an area. Growth rates are the annual changes in population resulting from births, deaths and net migration during the year. Total population includes the following: national armed forces stationed abroad; merchant seamen at sea; diplomatic personnel located abroad; civilian aliens resident in the country; displaced persons resident in the country. However, it excludes the following: foreign armed forces stationed in the country; foreign diplomatic personnel located in the country; civilian aliens temporarily in the country. Population projections are a common demographic tool. They provide a basis for other statistical projections, helping governments in their decision making. This indicator is measured in terms of annual growth rate and in thousands of people.

  • Citation: OECD (2024), Population (indicator). doi: 10.1787/d434f82b-en (Accessed on 28 January 2024)

df_oecd_pop <- read_csv("data/DP_LIVE_28012024064002957.csv")
Rows: 12264 Columns: 8── Column specification ─────────────────────────────────────────────────────────────────
Delimiter: ","
chr (5): LOCATION, INDICATOR, SUBJECT, MEASURE, FREQUENCY
dbl (2): TIME, Value
lgl (1): Flag Codes
ℹ Use `spec()` to retrieve the full column specification for this data.
ℹ Specify the column types or set `show_col_types = FALSE` to quiet this message.
df_oecd_pop
df_oecd_pop |> select(-Value) |> lapply(unique)
$LOCATION
 [1] "AUS"  "AUT"  "BEL"  "CAN"  "CZE"  "DNK"  "FIN"  "FRA"  "DEU"  "GRC"  "HUN"  "ISL" 
[13] "IRL"  "ITA"  "JPN"  "KOR"  "LUX"  "MEX"  "NLD"  "NZL"  "NOR"  "POL"  "PRT"  "SVK" 
[25] "ESP"  "SWE"  "CHE"  "TUR"  "GBR"  "USA"  "BRA"  "CHL"  "COL"  "EST"  "ISR"  "RUS" 
[37] "SVN"  "CHN"  "IND"  "IDN"  "ZAF"  "OECD" "LVA"  "ARG"  "BGR"  "CRI"  "HRV"  "CYP" 
[49] "LTU"  "MLT"  "ROU"  "SAU"  "SGP"  "WLD"  "G20"  "EU27"

$INDICATOR
[1] "POP"

$SUBJECT
[1] "MEN"   "TOT"   "WOMEN"

$MEASURE
[1] "MLN_PER"

$FREQUENCY
[1] "A"

$TIME
 [1] 1950 1951 1952 1953 1954 1955 1956 1957 1958 1959 1960 1961 1962 1963 1964 1965 1966
[18] 1967 1968 1969 1970 1971 1972 1973 1974 1975 1976 1977 1978 1979 1980 1981 1982 1983
[35] 1984 1985 1986 1987 1988 1989 1990 1991 1992 1993 1994 1995 1996 1997 1998 1999 2000
[52] 2001 2002 2003 2004 2005 2006 2007 2008 2009 2010 2011 2012 2013 2014 2015 2016 2017
[69] 2018 2019 2020 2021 2022

$`Flag Codes`
[1] NA
df_pop_short <- df_oecd_pop |> filter(SUBJECT == "TOT") |> select(iso3c = LOCATION, year = TIME, pop = Value)

Combine Three Datasets of OECD

Check the differences of countries in each datasets.

setdiff(df_fpop$iso3c, df_in$iso3c); setdiff(df_in$iso3c,df_fpop$iso3c)
[1] "HUN" "SVK" "SVN" "GRC" "ISL" "TUR" "CHL" "LVA" "LTU"
[1] "AUS" "NZL" "ISR" "RUS"
setdiff(df_fpop$iso3c, df_pop_short$iso3c); setdiff(df_in$iso3c, df_pop_short$iso3c)
character(0)
character(0)
  • “HUN” “SVK” “SVN” “GRC” “ISL” “TUR” “CHL” “LVA” “LTU” are in df_fpop but not in df_in.
  • “AUS” “NZL” “ISR” “RUS” are in df_in but not in df_fpop.
  • df_pop_short contains the data of countries in df_in and df_fpop.
df_fpop2 <- df_fpop |> select(iso3c, year, foreign)
df_oecd_fpop <- df_in |> full_join(df_fpop2, by = c("iso3c", "year")) |>
  left_join(df_pop_short, by = c("iso3c", "year")) |>
  mutate(foreign_pop = round(pop*10000*foreign), .after = value)
df_oecd_fpop
df_oecd_fpop |> filter(category == "TOT") |> drop_na(value, foreign) |>
  filter(value >0, foreign >0) |>
  ggplot(aes(value, foreign_pop)) + geom_point(aes(col = iso3c)) + scale_x_log10() + scale_y_log10() + geom_smooth(formula = 'y~x', method = "lm", se = FALSE)

UNdata - a world of information

https://data.un.org/

Popular statistical tables

Explorer - datamarts: http://data.un.org/Explorer.aspx

Join OECD Data with UN Data

df_oecd_un <- df_oecd_fpop |> left_join(df_un_migrants_ext_rev, by = c("country", "iso3c", "year")) |>
  select(country, iso3c, category, year, value, foreign_pop, foreign, pop, ser, migrants)
Warning: Detected an unexpected many-to-many relationship between `x` and `y`.
df_oecd_un
df_oecd_un |> filter(country == "Japan")
df_oecd_un_wide <- df_oecd_un |> drop_na(value, migrants) |> pivot_wider(names_from = category, values_from = value)  |>
  pivot_wider(names_from = ser, values_from = migrants)
df_oecd_un_wide
df_oecd_un_wide |> str()
tibble [117 × 21] (S3: tbl_df/tbl/data.frame)
 $ country        : chr [1:117] "Australia" "Australia" "Australia" "Australia" ...
 $ iso3c          : chr [1:117] "AUS" "AUS" "AUS" "AUS" ...
 $ year           : num [1:117] 2005 2010 2015 2020 2022 ...
 $ foreign_pop    : num [1:117] NA NA NA NA NA ...
 $ foreign        : num [1:117] NA NA NA NA NA 9.4 10.5 13.4 NA NA ...
 $ pop            : num [1:117] 20.2 22 23.8 25.7 26 ...
 $ FAM            : num [1:117] 43747 60254 61085 44442 54294 ...
 $ FAMWORKR       : num [1:117] 40739 61377 68292 51899 48041 ...
 $ FREEMOVS       : num [1:117] 22379 29051 25081 11915 9257 ...
 $ HUMNTRN        : num [1:117] 17528 14553 13759 13171 13307 ...
 $ OTH            : num [1:117] 1772 501 238 81 199 ...
 $ WORK           : num [1:117] 41154 46491 59482 43944 41022 ...
 $ TOT            : num [1:117] 167319 212227 227937 165452 166120 ...
 $ migrant        : num [1:117] 4878030 5882980 6729730 7685860 NA ...
 $ migrant_percent: num [1:117] 24.2 26.6 28.1 30.1 NA 13.7 15.2 17.1 19.3 NA ...
 $ migrant_male   : num [1:117] 24 26.4 28 30 NA 13.4 14.8 16.8 19.1 NA ...
 $ migrant_female : num [1:117] 24.3 26.7 28.2 30.3 NA 13.9 15.5 17.3 19.5 NA ...
 $ refugee        : num [1:117] 64964 21805 35582 58607 53523 ...
 $ asylum         : num [1:117] 1822 3760 22837 78800 84950 ...
 $ other          : num [1:117] 8 15 NA NA 17252 ...
 $ concern        : num [1:117] 66794 25580 58419 137407 148076 ...

Expenditure on educational institutions per full-time equivalent student

[Link]

Table in Excel, Filtered data in tableau text (CSV), Unfiltered data in tableau text (CSV) 136.4MB

temp <- read_csv("../../../bigdata/OECD.EDU.IMEP,DSD_EAG_UOE_FIN@DF_UOE_INDIC_FIN_PERSTUD,1.0+all.csv")
temp
library(readxl)
df_oecd_ed <- read_excel("data/OECD.EDU.IMEP,DSD_EAG_UOE_FIN@DF_UOE_INDIC_FIN_PERSTUD,1.0,filtered,2024-01-24 10-22-31.xlsx")
df_oecd_ed
df_oecd_ed <- read_excel("data/OECD.EDU.IMEP,DSD_EAG_UOE_FIN@DF_UOE_INDIC_FIN_PERSTUD,1.0,filtered,2024-01-24 10-22-31.xlsx", skip = 6)
df_oecd_ed
colnames(df_oecd_ed) 
df_oecd_ed_short <- df_oecd_ed |> select(1,3,4,5,6,9,10) |> drop_na(`Primary education`)
df_oecd_ed_short
df_oecd_ed2 <- read_csv("data/OECD.EDU.IMEP,DSD_EAG_UOE_FIN@DF_UOE_INDIC_FIN_PERSTUD,1.0+..ISCED11_1+ISCED11_2+ISCED11_3+ISCED11_4+ISCED11_5+ISCED11_5T8+ISCED11_6T8+ISCED11_1T8._T.INST_EDU.DIR_EXP...csv")
df_oecd_ed2

References

LS0tCnRpdGxlOiAiUHVibGljIERhdGEsIFJldmlzaXRlZCIKYXV0aG9yOiAiSUQsIExhc3QgTmFtZSwgRmlyc3QgTmFtZSIKZGF0ZTogIjIwMjQvMDEvMjQiCm91dHB1dDoKICBodG1sX25vdGVib29rOiBkZWZhdWx0CiAgaHRtbF9kb2N1bWVudDoKICAgIGRmX3ByaW50OiBwYWdlZAotLS0KCiMjIFNldHVwCgpJbnN0YWxsIGEgcGFja2FnZSBgY291bnRyeWNvZGVgIGZpcnN0LgoKYGBge3J9CmxpYnJhcnkodGlkeXZlcnNlKQpsaWJyYXJ5KFdESSkKbGlicmFyeShyZWFkeGwpCmxpYnJhcnkoY291bnRyeWNvZGUpCmBgYAoKIyMgV29ybGQgSW5lcXVhbGl0eSBEYXRhYmFzZQoKPGh0dHBzOi8vd2lkLndvcmxkPgoKIyMjIFdvcmxkIEluZXF1YWxpdHkgUmVwb3J0IDIwMjIKCi0gICBXb3JsZCBJbmVxdWFsaXR5IFJlcG9ydCAyMDIyOiA8aHR0cHM6Ly93aXIyMDIyLndpZC53b3JsZD4KCi0gICBNZXRob2RvbG9neSBbW0xpbmtdKGh0dHBzOi8vd2lyMjAyMi53aWQud29ybGQvbWV0aG9kb2xvZ3kvKV0KCipTaW5jZSBFeGNlbCBmaWxlcyBhcmUgYmluYXJ5IGZpbGUsIHlvdSBuZWVkIHRvIGFkZCBtb2RlID0gIndiIiwgd2ViIGJpbmFyeS4qCgpgYGB7cn0KdXJsX3N1bW1hcnkgPC0gImh0dHBzOi8vd2lyMjAyMi53aWQud29ybGQvd3d3LXNpdGUvdXBsb2Fkcy8yMDIyLzAzL1dJUjIwMjJUYWJsZXNGaWd1cmVzLVN1bW1hcnkueGxzeCIKZG93bmxvYWQuZmlsZSh1cmwgPSB1cmxfc3VtbWFyeSwgZGVzdGZpbGUgPSAiZGF0YS9XSVIyMDIycy54bHN4IiwgbW9kZSA9ICJ3YiIpCmBgYAoKYGBge3J9CmxpYnJhcnkocmVhZHhsKSAjIHJlYWR4bCBpcyBhIHBhcnQgb2YgdGlkeXZlcnNlIGJ1dCBub3QgYSBjb3JlIHBhY2thZ2UKYGBgCgpgYGB7cn0KZXhjZWxfc2hlZXRzKCJkYXRhL1dJUjIwMjJzLnhsc3giKQpgYGAKCmBgYHtyfQpkZl93aXJfZjIgPC0gcmVhZF9leGNlbCgiZGF0YS9XSVIyMDIycy54bHN4IiwgCiAgICBzaGVldCA9ICJkYXRhLUYyIikKZGZfd2lyX2YyCmBgYAoKQ3JlYXRlZCBhIG5ldyBFeGNlbCBib29rIHdpdGggb25seSBvbmUgc2hlZXQsIGFuZCBzYXZlIGl0IGFzIGEgQ1NWIFVURi04LgoKYGBge3J9CmRmX3dpcl9mMl8yIDwtIHJlYWRfY3N2KCJkYXRhL3dpci1mMi5jc3YiKQpkZl93aXJfZjJfMgpgYGAKCmBgYHtyfQpkZl93aXJfZjJfMiB8PiBpZGVudGljYWwoZGZfd2lyX2YyKQpgYGAKCmBgYHtyIGV2YWw9RkFMU0V9CmRmX3dpcl9mMl8zIDwtIHJlYWRfZGVsaW0oY2xpcGJvYXJkKCkpCmRmX3dpcl9mMl8zCmBgYAoKYGBge3J9CmRmX3dpcl9mMiB8PiBwaXZvdF9sb25nZXIoMzo1KSB8PiAKICBnZ3Bsb3QoYWVzKGlzbywgdmFsdWUsIGZpbGwgPSBuYW1lKSkgKyBnZW9tX2NvbChwb3NpdGlvbiA9ICJkb2RnZSIpICsgY29vcmRfZmxpcCgpCmBgYAoKU2VlOiA8aHR0cHM6Ly9kcy1zbC5naXRodWIuaW8vZGF0YS1hbmFseXNpcy93aXIyMDIyLm5iLmh0bWw+CgojIyMgVG8gc2hhcmUgZGF0YSB3aXRoIHNvbWVvbmUgZWxzZS4KCmBgYHtyfQpkcHV0KGRmX3dpcl9mMikKYGBgCgoKYGBge3J9CmRmX3dpcl9kcHV0IDwtIGRwdXQoZGZfd2lyX2YyKQpkZl93aXJfZHB1dApgYGAKCmBgYHtyfQpkZl93aXJfZjJfMyA8LSBkZl93aXJfZHB1dApkZl93aXJfZjJfMyB8PiBpZGVudGljYWwoZGZfd2lyX2YyKQpgYGAKCiMjIFVOZGF0YSAtIGEgd29ybGQgb2YgaW5mb3JtYXRpb24KCjxodHRwczovL2RhdGEudW4ub3JnLz4KClBvcHVsYXIgc3RhdGlzdGljYWwgdGFibGVzCgpFeHBsb3JlciAtIGRhdGFtYXJ0czogPGh0dHA6Ly9kYXRhLnVuLm9yZy9FeHBsb3Jlci5hc3B4PgoKLSAgIERhdGFzZXRzLCBTb3VyY2VzLCBUb3BpY3MKCiMjIyBQb3B1bGFyIHN0YXRpc3RpY2FsIHRhYmxlcwoKQ29weSB0aGUgbGluayBvZiBJbnRlcm5hdGlvbmFsIE1pZ3JhbnRzIGFuZCBSZWZ1Z2VlcwoKYGBge3J9CnVuX21pZ3JhbnRzX3VybCA8LSAiaHR0cHM6Ly9kYXRhLnVuLm9yZy9fRG9jcy9TWUIvQ1NWL1NZQjY2XzMyN18yMDIzMTBfSW50ZXJuYXRpb25hbCUyME1pZ3JhbnRzJTIwYW5kJTIwUmVmdWdlZXMuY3N2Igpkb3dubG9hZC5maWxlKHVuX21pZ3JhbnRzX3VybCwgZGVzdGZpbGUgPSAiZGF0YS9taWdyYW50cy5jc3YiKQpgYGAKCmBgYHtyfQpkZl91bl9taWdyYW50cyA8LSByZWFkX2NzdigiZGF0YS9taWdyYW50cy5jc3YiKQpkZl91bl9taWdyYW50cwpgYGAKCmBgYHtyfQpkZl91bl9taWdyYW50cyA8LSByZWFkX2NzdigiZGF0YS9taWdyYW50cy5jc3YiLCBza2lwPTEpCmRmX3VuX21pZ3JhbnRzCmBgYAoKCiMjIyBVTiBNaWdyYW50cyBEYXRhCgpgYGB7cn0KdXJsX3VuX21pZ3JhbnRzIDwtICJodHRwczovL2RhdGEudW4ub3JnL19Eb2NzL1NZQi9DU1YvU1lCNjZfMzI3XzIwMjMxMF9JbnRlcm5hdGlvbmFsJTIwTWlncmFudHMlMjBhbmQlMjBSZWZ1Z2Vlcy5jc3YiCmBgYAoKX1NpbmNlIHRoZSB1cmwgaXMgZ2l2ZW4sIGEgQ1NWIGZpbGUgY2FuIGJlIHJlYWQgZGlyZWN0bHkgdXNpbmcgYHJlYWRfY3N2YC5fCgpgYGB7cn0KZGZfdW5fbWlncmFudHMgPC0gcmVhZF9jc3YodXJsX3VuX21pZ3JhbnRzLCBza2lwID0gMSkKZGZfdW5fbWlncmFudHMKYGBgCgpgYGB7cn0Kc3RyKGRmX3VuX21pZ3JhbnRzKQpgYGAKCjwhLS0gIyMjIERvd25sb2FkIGRhdGEgLS0+Cgo8IS0tIGBgYHtyfSAtLT4KCjwhLS0gZG93bmxvYWQuZmlsZSh1cmxfdW5fbWlncmFudHMsIGRlc3RmaWxlID0gImRhdGEvdW5fbWlncmFudHMuY3N2IikgLS0+Cgo8IS0tIGBgYCAtLT4KCmBgYHtyfQpkZl91bl9taWdyYW50cyB8PiBzdW1tYXJ5KCkKYGBgCgpgYGB7cn0KZGZfdW5fbWlncmFudHMgfD4gc2VsZWN0KFllYXIsU2VyaWVzKSB8PiBsYXBwbHkodW5pcXVlKQpgYGAKCmBgYHtyIGV2YWwgPSBGQUxTRX0KZGZfdW5fbWlncmFudHMgfD4gZGlzdGluY3QoYFJlZ2lvbi9Db3VudHJ5L0FyZWFgLCAuLi4yKQpgYGAKCmBgYHtyfQpsaWJyYXJ5KGNvdW50cnljb2RlKQpkZl91bl9taWdyYW50cyAlPiUgbXV0YXRlKGlzbzJjX3VuID0gY291bnRyeWNvZGUoYFJlZ2lvbi9Db3VudHJ5L0FyZWFgLCAidW4iLCAiaXNvMmMiKSwgLmFmdGVyID0gLi4uMikKYGBgCgpgYGB7cn0KZGZfdW5fbWlncmFudHMgfD4gbXV0YXRlKGlzbzJjX3VuID0gY291bnRyeWNvZGUoYFJlZ2lvbi9Db3VudHJ5L0FyZWFgLCAidW4iLCAiaXNvMmMiKSwgLmFmdGVyID0gLi4uMikgfD4gZmlsdGVyKGlzLm5hKGlzbzJjX3VuKSkgfD4gZGlzdGluY3QoLi4uMikKYGBgCgpgYGB7cn0Kd2RpY2FjaGUgPC0gcmVhZF9yZHMoImRhdGEvd2RpY2FjaGUucmRzIikKd2RpX2NvdW50cnlfZXh0cmEgPC0gd2RpY2FjaGUkY291bnRyeSB8PiBzZWxlY3QoaXNvMmMsIHJlZ2lvbiwgaW5jb21lLCBsZW5kaW5nKQpgYGAKCmBgYHtyIGV2YWw9RkFMU0V9CmRmX3VuX21pZ3JhbnRzX2V4dCA8LSBkZl91bl9taWdyYW50cyAlPiUgCiAgbXV0YXRlKGlzbzJjX3VuID0gY291bnRyeWNvZGUoYFJlZ2lvbi9Db3VudHJ5L0FyZWFgLCAidW4iLCAiaXNvMmMiKSwgLmFmdGVyID0gLi4uMikgfD4KICBkcm9wX25hKGlzbzJjX3VuKSB8PiAKICBzZWxlY3QoQ291bnRyeSA9IC4uLjIsIElTTzJDID0gaXNvMmNfdW4sIFllYXIsIFNlcmllcywgVmFsdWUsIEZvb3Rub3RlcykgfD4KICBsZWZ0X2pvaW4od2RpX2NvdW50cnlfZXh0cmEsIGJ5ID0gYygiSVNPMkMiID0gImlzbzJjIikpCmRmX3VuX21pZ3JhbnRzX2V4dApgYGAKCmBgYHtyIGVjaG89RkFMU0V9CmRmX3VuX21pZ3JhbnRzX2V4dCA8LSBkZl91bl9taWdyYW50cyAlPiUgCiAgbXV0YXRlKGlzbzJjX3VuID0gY291bnRyeWNvZGUoYFJlZ2lvbi9Db3VudHJ5L0FyZWFgLCAidW4iLCAiaXNvMmMiKSwgLmFmdGVyID0gLi4uMikgfD4KICBkcm9wX25hKGlzbzJjX3VuKSB8PiAKICBzZWxlY3QoQ291bnRyeSA9IC4uLjIsIElTTzJDID0gaXNvMmNfdW4sIFllYXIsIFNlcmllcywgVmFsdWUsIEZvb3Rub3RlcykgfD4KICBsZWZ0X2pvaW4od2RpX2NvdW50cnlfZXh0cmEsIGJ5ID0gYygiSVNPMkMiID0gImlzbzJjIikpCmRmX3VuX21pZ3JhbnRzX2V4dApgYGAKCmBgYHtyfQpkZl91bl9taWdyYW50c19leHQkU2VyaWVzIHw+IHVuaXF1ZSgpCmBgYAoKYGBge3J9CmRmX3VuX21pZ3JhbnRzX2V4dF9yZXYgPC0gZGZfdW5fbWlncmFudHNfZXh0IHw+IG11dGF0ZShTZXIgPSBjYXNlX3doZW4oCiAgU2VyaWVzID09ICJJbnRlcm5hdGlvbmFsIG1pZ3JhbnQgc3RvY2s6IEJvdGggc2V4ZXMgKG51bWJlcikiIH4gIm1pZ3JhbnQiLAogIFNlcmllcyA9PSAiSW50ZXJuYXRpb25hbCBtaWdyYW50IHN0b2NrOiBCb3RoIHNleGVzICglIHRvdGFsIHBvcHVsYXRpb24pIiB+ICJtaWdyYW50X3BlcmNlbnQiLAogIFNlcmllcyA9PSAiSW50ZXJuYXRpb25hbCBtaWdyYW50IHN0b2NrOiBNYWxlICglIHRvdGFsIFBvcHVsYXRpb24pIiB+ICJtaWdyYW50X21hbGUiLAogIFNlcmllcyA9PSAiSW50ZXJuYXRpb25hbCBtaWdyYW50IHN0b2NrOiBGZW1hbGUgKCUgdG90YWwgUG9wdWxhdGlvbikiIH4gIm1pZ3JhbnRfZmVtYWxlIiwKICBTZXJpZXMgPT0gIlRvdGFsIHJlZnVnZWVzIGFuZCBwZW9wbGUgaW4gcmVmdWdlZS1saWtlIHNpdHVhdGlvbnMgKG51bWJlcikiIH4gInJlZnVnZWUiLAogIFNlcmllcyA9PSAiQXN5bHVtIHNlZWtlcnMsIGluY2x1ZGluZyBwZW5kaW5nIGNhc2VzIChudW1iZXIpIiB+ICJhc3lsdW0iLAogIFNlcmllcyA9PSAiT3RoZXIgb2YgY29uY2VybiB0byBVTkhDUiAobnVtYmVyKSIgIH4gIm90aGVyIiwKICBTZXJpZXMgPT0gIlRvdGFsIHBvcHVsYXRpb24gb2YgY29uY2VybiB0byBVTkhDUiAobnVtYmVyKSIgfiAiY29uY2VybiIsCiAgVFJVRSB+IFNlcmllcyksIC5iZWZvcmUgPSBTZXJpZXMpCmBgYAoKYGBge3J9CmRmX3VuX21pZ3JhbnRzX2V4dF9yZXYKYGBgCgpgYGB7ciBldmFsPUZBTFNFfQpkcHV0KGRmX3VuX21pZ3JhbnRzX2V4dF9yZXYpCmBgYAoKCiMjIyBFeHBsb3JlciAtIGRhdGFtYXJ0cwoKRW52aXJvbm1lbnQgU3RhdGlzdGljcyBEYXRhYmFzZVw+V2F0ZXJcPkludGVybmFsIGZsb3cgW1tMaW5rXShodHRwOi8vZGF0YS51bi5vcmcvRGF0YS5hc3B4P2Q9RU5WJmY9dmFyaWFibGVJRDo1JmM9MiwzLDQsNSZzPWNvdW50cnlOYW1lOmFzYyx5cjpkZXNjJnY9MSldCgoqU2VsZWN0IGNvbHVtbnMgdG8gYWRkIFRhYmxlIElEIGFuZCBDb3VudHJ5IGFuZCBBcmVhIENvZGUgb2YgVU4sIGFuZCBkb3dubG9hZCAnQ29tbWEnIGEgQ1NWLioKCmBgYHtyfQpkZl91bl93YXRlciA8LSByZWFkX2NzdigiZGF0YS9VTmRhdGFfRXhwb3J0XzIwMjQwMTI0XzAxMDYwOTY3MS5jc3YiKQpkZl91bl93YXRlcgpgYGAKCgojIyBPRUNEIGRhdGEKCiMjIyBPRUNEIGRhdGEgdG9wCgpPRUNEIGRhdGEgPGh0dHBzOi8vZGF0YS5vZWNkLm9yZy8+CiAgCiAgLSBCcm93c2UgYnkgVG9waWNzIChDaG9vc2UgZnJvbSAxMiB0b3BpY3MpIG9yIENvdW50cnkgKENob29zZSBmcm9tIDM3IGNvdW50cmllcykKICAtIFRvcGljczogCiAgICAtIEFncmljdWx0dXJlLCAKICAgIC0gRGV2ZWxvcG1lbnQsIAogICAgLSBFY29ub215LCAKICAgIC0gRWR1Y2F0aW9uLCAKICAgIC0gRW5lcmd5LCAKICAgIC0gRW52aXJvbm1lbnQsIAogICAgLSBGaW5hbmNlLCAKICAgIC0gR292ZXJubWVudCwgCiAgICAtIEhlYWx0aCwgCiAgICAtIElubm92YXRpb24gYW5kIFRlY2hub2xvZ3ksIAogICAgLSBKb2JzLCAKICAgIC0gU29jaWV0eQogICAgICAtIERlbW9ncmFwaHkKICAgICAgLSBJbmVxdWFsaXR5CiAgICAgIC0gTWlncmF0aW9uCiAgICAgIC0gUG9wdWxhdGlvbiBieSBSZWdpb24KICAgICAgLSBTb2NpYWwgcHJvdGVjdGlvbgogIC0gQ291bnRyaWVzOgogICAgLSBBdXN0cmFsaWEsIEF1c3RyaWEsIEJlbGdpdW0sIEJyYXppbCwgQ2FuYWRhLCBDaGlsaSwgUGVvcGxlJ3MgUmVwdWJsaWMgb2YgQ2hpbmEsIENvbHVtYmlhLCBDb3N0YSBSaWNhLCBDemVjaGlhLCBEZW5tYXJrLCBFc3RvbmlhLCBGaW5sYW5kLCBGcmFuY2UsIEdlcm1hbnksIEdyZWVjZSwgSHVuZ2FyeSwgSWNlbGFuZCwgSW5kaWEsIEluZG9uZXNpYSwgSXJlbGFuZCwgSXNsYWVsLCBJdGFseSwgSmFwYW4sIEtvcmVhLCBMYXR2aWEsIExpdGh1YW5pYSwgTHV4ZW1ib3VyZywgTWV4aWNvLCBOZXRoZXJsYW5kcywgTmV3IFplYWxhbmQsIE5vcndheSwgUG9sYW5kLCBQb3J0dWdhbCwgUnVzc2lhbiBGZWRlcmF0aW9uLCBTbG92YWsgUmVwdWJsaWMsIFNsb3ZlbmlhLCBTb3V0aCBBZnJpY2EsIFNwYWluLCBTd2VkZW4sIFN3aXplcmxhbmQsIFTDvHJraXllLCBVbml0ZWQgS2luZ2RvbSwgVW5pdGVkIFN0YXRlcyAKICAKCiMjIyMgRGF0YWJhc2UgQWNjZXNzOiA8aHR0cHM6Ly9kYXRhLWV4cGxvcmVyLm9lY2Qub3JnLz4KClRoZXJlIGlzIGEgbmV3bHkgZGV2ZWxvcGVkIERhdGFiYXNlIEFjY2VzcyBsaW5rZWQgYWJvdmUuIEhvd2V2ZXIsIGl0IGlzIHN0aWxsIHVuZGVyIGRldmVsb3BtZW50IGFuZCBkaWZmaWN1bHQgdG8gaGFuZGxlIGRhdGEgdGhlcmUuCgojIyMgVG9waWM6IFNvY2lldHkgLSBNaWdyYXRpb24KCi0gUGVybWFuZW50IGltbWlncmFudCBpbmZsb3dzCiAgLSBQZXJtYW5lbnQgaW1taWdyYW50IGluZmxvd3MgY292ZXIgcmVndWxhdGVkIG1vdmVtZW50cyBvZiBmb3JlaWduZXJzIGNvbnNpZGVyZWQgdG8gYmUgc2V0dGxpbmcgaW4gdGhlIGNvdW50cnkgZnJvbSB0aGUgcGVyc3BlY3RpdmUgb2YgdGhlIGRlc3RpbmF0aW9uIGNvdW50cnkuIFRoZXkgY292ZXIgcmVndWxhdGVkIG1vdmVtZW50cyBvZiBmb3JlaWduZXJzIGFzIHdlbGwgYXMgZnJlZSBtb3ZlbWVudCBtaWdyYXRpb24uIFRoZSBkYXRhIHByZXNlbnRlZCBhcmUgdGhlIHJlc3VsdCBvZiBhIHN0YW5kYXJkaXNhdGlvbiBwcm9jZXNzIHRoYXQgYWxsb3dzIGZvciBjcm9zcy1jb3VudHJ5IGNvbXBhcmlzb25zLiBUaGlzIGluZGljYXRvciBpcyBtZWFzdXJlZCBieSBudW1iZXJzIG9mIHBlcm1hbmVudCBpbmZsb3dzLgotIFN0b2NrcyBvZiBmb3JlaWduLWJvcm4gcG9wdWxhdGlvbiBpbiBPRUNEIGNvdW50cmllcwotIEZvcmVpZ24tYm9ybiBwb3B1bGF0aW9uCi0gRm9yZWlnbiBwb3B1bGF0aW9uCi0gTmF0aXZlLWJvcm4gZW1wbG95bWVudAotIEZvcmVpZ24tYm9ybiBlbXBsb3ltZW50Ci0gTmF0aXZlLWJvcm4gdW5lbXBsb3ltZW50Ci0gRm9yZWlnbi1ib3JuIHVuZW1wbG95bWVudAotIE5hdGl2ZS1ib3JuIHBhcnRpY2lwYXRpb24gcmF0ZXMKLSBGb3JlaWduLWJvcm4gcGFydGljaXBhdGlvbiByYXRlcwoKIyMjIFBlcm1hbmVudCBpbW1pZ3JhbnQgaW5mbG93cwoKUGVybWFuZW50IGltbWlncmFudCBpbmZsb3dzIFRvdGFsLCBOdW1iZXIsIDIwMjIgW0xpbmtdKGh0dHBzOi8vZGF0YS5vZWNkLm9yZy9taWdyYXRpb24vcGVybWFuZW50LWltbWlncmFudC1pbmZsb3dzLmh0bSkKCkRlZmluaXRpb24gb2YgUGVybWFuZW50IGltbWlncmFudCBpbmZsb3dzCgogIC0gUGVybWFuZW50IGltbWlncmFudCBpbmZsb3dzIGNvdmVyIHJlZ3VsYXRlZCBtb3ZlbWVudHMgb2YgZm9yZWlnbmVycyBjb25zaWRlcmVkIHRvIGJlIHNldHRsaW5nIGluIHRoZSBjb3VudHJ5IGZyb20gdGhlIHBlcnNwZWN0aXZlIG9mIHRoZSBkZXN0aW5hdGlvbiBjb3VudHJ5LiBUaGV5IGNvdmVyIHJlZ3VsYXRlZCBtb3ZlbWVudHMgb2YgZm9yZWlnbmVycyBhcyB3ZWxsIGFzIGZyZWUgbW92ZW1lbnQgbWlncmF0aW9uLiBUaGUgZGF0YSBwcmVzZW50ZWQgYXJlIHRoZSByZXN1bHQgb2YgYSBzdGFuZGFyZGlzYXRpb24gcHJvY2VzcyB0aGF0IGFsbG93cyBmb3IgY3Jvc3MtY291bnRyeSBjb21wYXJpc29ucy4gVGhpcyBpbmRpY2F0b3IgaXMgbWVhc3VyZWQgYnkgbnVtYmVycyBvZiBwZXJtYW5lbnQgaW5mbG93cy4KICAtIENpdGF0aW9uOiBPRUNEICgyMDI0KSwgUGVybWFuZW50IGltbWlncmFudCBpbmZsb3dzIChpbmRpY2F0b3IpLiBkb2k6IDEwLjE3ODcvMzA0NTQ2YjYtZW4gKEFjY2Vzc2VkIG9uIDI3IEphbnVhcnkgMjAyNCkKICAKYGBgez1odG1sfQo8aWZyYW1lIHNyYz0iaHR0cHM6Ly9kYXRhLm9lY2Qub3JnL2NoYXJ0LzdrZ2siIHdpZHRoPSI4NjAiIGhlaWdodD0iNjQ1IiBzdHlsZT0iYm9yZGVyOiAwIiBtb3phbGxvd2Z1bGxzY3JlZW49InRydWUiIHdlYmtpdGFsbG93ZnVsbHNjcmVlbj0idHJ1ZSIgYWxsb3dmdWxsc2NyZWVuPSJ0cnVlIj48YSBocmVmPSJodHRwczovL2RhdGEub2VjZC5vcmcvY2hhcnQvN2tnayIgdGFyZ2V0PSJfYmxhbmsiPk9FQ0QgQ2hhcnQ6IFBlcm1hbmVudCBpbW1pZ3JhbnQgaW5mbG93cywgVG90YWwsIE51bWJlciwgQW5udWFsLCAyMDIyPC9hPjwvaWZyYW1lPgpgYGAKCmBgYHtyLCByZXN1bHRzPSdhc2lzJ30KbGlicmFyeShodG1sdG9vbHMpCgppZnJhbWVfY29kZSA8LSAnPGlmcmFtZSBzcmM9Imh0dHBzOi8vZGF0YS5vZWNkLm9yZy9jaGFydC83a2drIiB3aWR0aD0iODYwIiBoZWlnaHQ9IjY0NSIgc3R5bGU9ImJvcmRlcjogMCIgbW96YWxsb3dmdWxsc2NyZWVuPSJ0cnVlIiB3ZWJraXRhbGxvd2Z1bGxzY3JlZW49InRydWUiIGFsbG93ZnVsbHNjcmVlbj0idHJ1ZSI+PGEgaHJlZj0iaHR0cHM6Ly9kYXRhLm9lY2Qub3JnL2NoYXJ0LzdrZ2siIHRhcmdldD0iX2JsYW5rIj5PRUNEIENoYXJ0OiBQZXJtYW5lbnQgaW1taWdyYW50IGluZmxvd3MsIFRvdGFsLCBOdW1iZXIsIEFubnVhbCwgMjAyMjwvYT48L2lmcmFtZT4nCgpIVE1MKGlmcmFtZV9jb2RlKQpgYGAKCiMjIyBPRUNEOiBQZXJtYW5lbnQgaW1taWdyYW50IGluZmxvd3MKCiMjIyMgRGF0YSBJbmZvcm1hdGlvbgoKLSAgIERhdGEgU2l0ZTogaHR0cHM6Ly9kYXRhLm9lY2Qub3JnL21pZ3JhdGlvbi9wZXJtYW5lbnQtaW1taWdyYW50LWluZmxvd3MuaHRtCgotICAgRGVmaW5pdGlvbiBvZiBQZXJtYW5lbnQgaW1taWdyYW50IGluZmxvd3M6IApQZXJtYW5lbnQgaW1taWdyYW50IGluZmxvd3MgY292ZXIgcmVndWxhdGVkIG1vdmVtZW50cyBvZiBmb3JlaWduZXJzIGNvbnNpZGVyZWQgdG8gYmUgc2V0dGxpbmcgaW4gdGhlIGNvdW50cnkgZnJvbSB0aGUgcGVyc3BlY3RpdmUgb2YgdGhlIGRlc3RpbmF0aW9uIGNvdW50cnkuIFRoZXkgY292ZXIgcmVndWxhdGVkIG1vdmVtZW50cyBvZiBmb3JlaWduZXJzIGFzIHdlbGwgYXMgZnJlZSBtb3ZlbWVudCBtaWdyYXRpb24uIFRoZSBkYXRhIHByZXNlbnRlZCBhcmUgdGhlIHJlc3VsdCBvZiBhIHN0YW5kYXJkaXNhdGlvbiBwcm9jZXNzIHRoYXQgYWxsb3dzIGZvciBjcm9zcy1jb3VudHJ5IGNvbXBhcmlzb25zLiBUaGlzIGluZGljYXRvciBpcyBtZWFzdXJlZCBieSBudW1iZXJzIG9mIHBlcm1hbmVudCBpbmZsb3dzLgoKLSAgIENpdGF0aW9uOiBPRUNEICgyMDI0KSwgUGVybWFuZW50IGltbWlncmFudCBpbmZsb3dzIChpbmRpY2F0b3IpLiBkb2k6IDEwLjE3ODcvMzA0NTQ2YjYtZW4gKEFjY2Vzc2VkIG9uIDI4IEphbnVhcnkgMjAyNCkKCi0gICBDYXRlZ29yaWVzOiBUb3RhbCwgV29yaywgRnJlZSBtb3ZlbWVudHMsIEZhbWlseSwgRmFtaWx5IGFjY29tcGFueWluZyB3b3JrZXJzLCBIdW1hbml0YXJpYW4sIE90aGVyCgpgYGB7cn0KbGlicmFyeSh0aWR5dmVyc2UpCmBgYApSZWFkIHRoZSBkb3dubG9hZGVkIGZ1bGwgZGF0YSBvZiAnUGVybWFuZW50IEltbWlncmFudCBJbmZsb3dzJy4KCmBgYHtyfQpkZl9pbmZsb3dzIDwtIHJlYWRfY3N2KCJkYXRhL0RQX0xJVkVfMjgwMTIwMjQwMDQxMTcyNzkuY3N2IikKYGBgCmBgYHtyfQpkZl9pbmZsb3dzCmBgYAoKYGBge3J9CmRmX2luZmxvd3MgfD4gc2VsZWN0KC1WYWx1ZSkgfD4gbGFwcGx5KHVuaXF1ZSkKYGBgCgpTZXQgdGhlIG9yZGVyIG9mIGNhdGVnb3JpZXMgdG8gZGlzcGxheS4KCmBgYHtyfQpDQVQgPC0gYygiVE9UIiwgIldPUksiLCAiRlJFRU1PVlMiLCAiRkFNIiwgIkZBTVdPUktSIiwgIkhVTU5UUk4iLCAiT1RIIikKYGBgCgpBZGQgY291bnRyeSBuYW1lcyB1c2luZyB0aGUgYGNvdW50cnljb2RlYCBwYWNrYWdlIGFuZCBkZWxldGUgSU5ESUNBVE9SLCBNRUFTVVJFLCBGUkVRVUVOQ1ksIEZsYWcgQ29kZXMuCgpgYGB7cn0KZGZfaW4gPC0gZGZfaW5mbG93cyB8PiAKICBtdXRhdGUoY291bnRyeSA9IGNvdW50cnljb2RlKExPQ0FUSU9OLCAiaXNvM2MiLCAiY291bnRyeS5uYW1lIiksIC5iZWZvcmUgPSBMT0NBVElPTikgfD4gCiAgc2VsZWN0KGNvdW50cnksIGlzbzNjID0gTE9DQVRJT04sIGNhdGVnb3J5ID0gU1VCSkVDVCwgeWVhciA9IFRJTUUsIHZhbHVlID0gVmFsdWUpCmRmX2luCmBgYAoKYGBge3J9CmRmX2luIHw+IGZpbHRlcihjb3VudHJ5ID09ICJKYXBhbiIpIHw+IAogIGdncGxvdChhZXMoeWVhciwgdmFsdWUsIGNvbCA9IGZhY3RvcihjYXRlZ29yeSwgbGV2ZWxzID0gQ0FUKSkpICsgZ2VvbV9saW5lKCkgKyAKICBsYWJzKGNvbCA9ICJDYXRlZ29yaWVzIikKYGBgCgoKYGBge3J9CmRmX2luIHw+IGZpbHRlcihjb3VudHJ5ID09ICJKYXBhbiIpIHw+IGZpbHRlcihjYXRlZ29yeSAhPSAiVE9UIikgfD4gCiAgZ2dwbG90KGFlcyh5ZWFyLCB2YWx1ZSwgZmlsbCA9IGZhY3RvcihjYXRlZ29yeSwgbGV2ZWxzID0gcmV2KENBVCkpKSkgKyAKICBnZW9tX2FyZWEoY29sID0gImJsYWNrIiwgbGluZXdpZHRoID0gMC4xKSArCiAgbGFicyh0aXRsZSA9ICJQZXJtYW5lbnQgaW1taWdyYW50IGluZmxvd3Mgb2YgSmFwYW4iLCBmaWxsID0gIkNhdGVnb3JpZXMiKQpgYGAKCmBgYHtyIGZpZy5oZWlnaHQ9NywgZmlnLndpZHRoPTd9CmRmX2luIHw+IGZpbHRlcihjYXRlZ29yeSAhPSAiVE9UIikgfD4gCiAgZ2dwbG90KGFlcyh5ZWFyLCB2YWx1ZSwgZmlsbCA9IGZhY3RvcihjYXRlZ29yeSwgbGV2ZWxzID0gcmV2KENBVCkpKSkgKyBnZW9tX2FyZWEoY29sID0gImJsYWNrIiwgbGluZXdpZHRoID0gMC4xKSArCiAgZmFjZXRfd3JhcCh+Y291bnRyeSkgKyAKICBsYWJzKHRpdGxlID0gIlBlcm1hbmVudCBpbW1pZ3JhbnQgaW5mbG93cyBvZiAyOCBDb3VudHJpZXMiLCBmaWxsID0gIiIpICsKICB0aGVtZShsZWdlbmQucG9zaXRpb24gPSAnYm90dG9tJykKYGBgCgpgYGB7cn0KZGZfaW4gfD4gZmlsdGVyKGNvdW50cnkgJWluJSBjKCJHZXJtYW55IiwgIlVuaXRlZCBTdGF0ZXMiKSkgfD4gCiAgZ2dwbG90KGFlcyh5ZWFyLCB2YWx1ZSwgY29sID0gY291bnRyeSwgbGluZXR5cGUgPSBmYWN0b3IoY2F0ZWdvcnksIGxldmVscyA9IENBVCkpKSArIGdlb21fbGluZSgpICsKICBsYWJzKHRpdGxlID0gIlBlcm1hbmVudCBpbW1pZ3JhbnQgaW5mbG93cyBvZiBHZXJtYW55IGFuZCBVbml0ZWQgU3RhdGVzIiwgbGluZXR5cGUgPSAiQ2F0ZWdvcmllcyIpCmBgYAoKYGBge3IgZmlnLmhlaWdodD03LCBmaWcud2lkdGg9N30KdG90X2xldiA8LSBkZl9pbiB8PiBwaXZvdF93aWRlcihuYW1lc19mcm9tID0gY2F0ZWdvcnksIHZhbHVlc19mcm9tID0gdmFsdWUpIHw+IAogIHBpdm90X2xvbmdlcihjb2xzID0gQ0FUW0NBVCE9IlRPVCJdLCBuYW1lc190byA9ICJjYXRlZ29yeSIsIHZhbHVlc190byA9ICJ2YWx1ZSIpIHw+IGZpbHRlcih5ZWFyID09IDIwMjIpIHw+IGRpc3RpbmN0KGNvdW50cnksIGlzbzNjLCBUT1QpIHw+IGFycmFuZ2UoZGVzYyhUT1QpKSB8PiBwdWxsKGNvdW50cnkpCmRmX2luIHw+IHBpdm90X3dpZGVyKG5hbWVzX2Zyb20gPSBjYXRlZ29yeSwgdmFsdWVzX2Zyb20gPSB2YWx1ZSkgfD4gCiAgcGl2b3RfbG9uZ2VyKGNvbHMgPSBDQVRbQ0FUIT0iVE9UIl0sIG5hbWVzX3RvID0gImNhdGVnb3J5IiwgdmFsdWVzX3RvID0gInZhbHVlIikgfD4gZmlsdGVyKHllYXIgPT0gMjAyMikgfD4gZ2dwbG90KGFlcyhmYWN0b3IoY291bnRyeSwgbGV2ZWxzID0gcmV2KHRvdF9sZXYpKSwgdmFsdWUsIGZpbGwgPSBmYWN0b3IoY2F0ZWdvcnksIGxldmVscyA9IENBVCkpKSArIGdlb21fY29sKGNvbCA9ICJibGFjayIsIGxpbmV3aWR0aCA9IDAuMSkgKyBjb29yZF9mbGlwKCkgKwogIGxhYnModGl0bGUgPSAiUGVybWFuZW50IGltbWlncmFudCBpbmZsb3dzIGluIDIwMjIiLCBmaWxsID0gIiIsIHggPSAiIikgKwogIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbiA9ICdib3R0b20nKQpgYGAKCgojIyMgT0VDRDogRm9yZWlnbiBwb3B1bGF0aW9uCgojIyMjIERhdGEgSW5mb3JtYXRpb24KCi0gICBEYXRhIFNpdGU6IGh0dHBzOi8vZGF0YS5vZWNkLm9yZy9taWdyYXRpb24vZm9yZWlnbi1wb3B1bGF0aW9uLmh0bQoKLSAgIERlZmluaXRpb24gb2YgRm9yZWlnbiBwb3B1bGF0aW9uOiAKVGhlIGZvcmVpZ24gcG9wdWxhdGlvbiBjb25zaXN0cyBvZiBwZW9wbGUgd2hvIHN0aWxsIGhhdmUgdGhlIG5hdGlvbmFsaXR5IG9mIHRoZWlyIGhvbWUgY291bnRyeS4gSXQgbWF5IGluY2x1ZGUgcGVvcGxlIGJvcm4gaW4gdGhlIGhvc3QgY291bnRyeS4gVGhlIGRpZmZlcmVuY2UgYWNyb3NzIGNvdW50cmllcyBiZXR3ZWVuIHRoZSBzaXplIG9mIHRoZSBmb3JlaWduLWJvcm4gcG9wdWxhdGlvbiBhbmQgdGhhdCBvZiB0aGUgZm9yZWlnbiBwb3B1bGF0aW9uIGRlcGVuZHMgb24gdGhlIHJ1bGVzIGdvdmVybmluZyB0aGUgYWNxdWlzaXRpb24gb2YgY2l0aXplbnNoaXAgaW4gZWFjaCBjb3VudHJ5LiBUaGlzIGluZGljYXRvciBpcyBtZWFzdXJlZCBhcyBhIHBlcmNlbnRhZ2Ugb2YgcG9wdWxhdGlvbi4KCi0gICBDaXRhdGlvbjogT0VDRCAoMjAyNCksIEZvcmVpZ24gcG9wdWxhdGlvbiAoaW5kaWNhdG9yKS4gZG9pOiAxMC4xNzg3LzE2YTkxNGUzLWVuIChBY2Nlc3NlZCBvbiAyOCBKYW51YXJ5IDIwMjQpCgotICAgQ2F0ZWdvcmllczogVG90YWwsIFBlcmNlbnQgb2YgUG9wdWxhdGlvbgoKUmVhZCB0aGUgZG93bmxvYWRlZCBmdWxsIGRhdGEgb2YgJ0ZvcmVpZ24gcG9wdWxhdGlvbicuCgpgYGB7cn0KZGZfZm9yZWlnbiA8LSByZWFkX2NzdigiZGF0YS9EUF9MSVZFXzI4MDEyMDI0MDA0MjAwMTI0LmNzdiIpCmBgYApgYGB7cn0KZGZfZm9yZWlnbgpgYGAKCmBgYHtyfQpkZl9mb3JlaWduIHw+IHNlbGVjdCgtVmFsdWUpIHw+IGxhcHBseSh1bmlxdWUpCmBgYAoKQWRkIGNvdW50cnkgbmFtZXMgdXNpbmcgdGhlIGBjb3VudHJ5Y29kZWAgcGFja2FnZSBhbmQgZGVsZXRlIElORElDQVRPUiwgTUVBU1VSRSwgRlJFUVVFTkNZLCBGbGFnIENvZGVzLgoKYGBge3J9CmRmX2Zwb3AgPC0gZGZfZm9yZWlnbiB8PiAKICBtdXRhdGUoY291bnRyeSA9IGNvdW50cnljb2RlKExPQ0FUSU9OLCAiaXNvM2MiLCAiY291bnRyeS5uYW1lIiksIC5iZWZvcmUgPSBMT0NBVElPTikgfD4gCiAgc2VsZWN0KGNvdW50cnksIGlzbzNjID0gTE9DQVRJT04sIHllYXIgPSBUSU1FLCBmb3JlaWduID0gVmFsdWUpCmRmX2Zwb3AKYGBgCgpgYGB7cn0KZGZfZnBvcCB8PiBmaWx0ZXIoY291bnRyeSA9PSAiSmFwYW4iKSB8PiAKICBnZ3Bsb3QoYWVzKHllYXIsIGZvcmVpZ24pKSArIGdlb21fbGluZSgpICsgCiAgbGFicyh0aXRsZSA9ICJGb3JlaWduIFBvcHVsYXRpb24gaW4gSmFwYW4gKFBlcmNlbnQpIikKYGBgCgoKYGBge3J9CmRmX2Zwb3AgfD4gCiAgZ2dwbG90KGFlcyh5ZWFyLCBmb3JlaWduKSkgKyBnZW9tX2xpbmUoYWVzKGNvbCA9IGlzbzNjKSkgKyAKICBnZW9tX3Ntb290aChmb3JtdWxhID0gJ3l+eCcsIG1ldGhvZCA9ICJsb2VzcyIsIHNlID0gRkFMU0UpICsgCiAgbGFicyh0aXRsZSA9ICJUb3RhbCBGb3JlaWduIFBvcHVsYXRpb24gKCUpIikKYGBgCgpgYGB7cn0KZGZfZnBvcCB8PiBmaWx0ZXIoeWVhciA9PSAyMDE5KSB8PiAKICBnZ3Bsb3QoYWVzKGZjdF9yZW9yZGVyKGNvdW50cnksIGZvcmVpZ24pLCBmb3JlaWduKSkgKyBnZW9tX2NvbCgpICsgCiAgY29vcmRfZmxpcCgpICsgbGFicyh0aXRsZSA9ICJGb3JlaWduIFBvcHVsYXRpb24gKCUpIiwgeCA9ICIiLCB5ID0gIiIpCmBgYAoKCgojIyMgT0VDRDogUG9wdWxhdGlvblRvdGFsLCBNaWxsaW9uIHBlcnNvbnMsIDIwMjIgb3IgbGF0ZXN0IGF2YWlsYWJsZQoKIyMjIyBEYXRhIEluZm9ybWF0aW9uCgotICAgRGF0YSBTaXRlOiBodHRwczovL2RhdGEub2VjZC5vcmcvcG9wL3BvcHVsYXRpb24uaHRtCgotICAgRGVmaW5pdGlvbiBvZiBQb3B1bGF0aW9uOiBQb3B1bGF0aW9uIGlzIGRlZmluZWQgYXMgYWxsIG5hdGlvbmFscyBwcmVzZW50IGluLCBvciB0ZW1wb3JhcmlseSBhYnNlbnQgZnJvbSBhIGNvdW50cnksIGFuZCBhbGllbnMgcGVybWFuZW50bHkgc2V0dGxlZCBpbiBhIGNvdW50cnkuIFRoaXMgaW5kaWNhdG9yIHNob3dzIHRoZSBudW1iZXIgb2YgcGVvcGxlIHRoYXQgdXN1YWxseSBsaXZlIGluIGFuIGFyZWEuIEdyb3d0aCByYXRlcyBhcmUgdGhlIGFubnVhbCBjaGFuZ2VzIGluIHBvcHVsYXRpb24gcmVzdWx0aW5nIGZyb20gYmlydGhzLCBkZWF0aHMgYW5kIG5ldCBtaWdyYXRpb24gZHVyaW5nIHRoZSB5ZWFyLiBUb3RhbCBwb3B1bGF0aW9uIGluY2x1ZGVzIHRoZSBmb2xsb3dpbmc6IG5hdGlvbmFsIGFybWVkIGZvcmNlcyBzdGF0aW9uZWQgYWJyb2FkOyBtZXJjaGFudCBzZWFtZW4gYXQgc2VhOyBkaXBsb21hdGljIHBlcnNvbm5lbCBsb2NhdGVkIGFicm9hZDsgY2l2aWxpYW4gYWxpZW5zIHJlc2lkZW50IGluIHRoZSBjb3VudHJ5OyBkaXNwbGFjZWQgcGVyc29ucyByZXNpZGVudCBpbiB0aGUgY291bnRyeS4gSG93ZXZlciwgaXQgZXhjbHVkZXMgdGhlIGZvbGxvd2luZzogZm9yZWlnbiBhcm1lZCBmb3JjZXMgc3RhdGlvbmVkIGluIHRoZSBjb3VudHJ5OyBmb3JlaWduIGRpcGxvbWF0aWMgcGVyc29ubmVsIGxvY2F0ZWQgaW4gdGhlIGNvdW50cnk7IGNpdmlsaWFuIGFsaWVucyB0ZW1wb3JhcmlseSBpbiB0aGUgY291bnRyeS4gUG9wdWxhdGlvbiBwcm9qZWN0aW9ucyBhcmUgYSBjb21tb24gZGVtb2dyYXBoaWMgdG9vbC4gVGhleSBwcm92aWRlIGEgYmFzaXMgZm9yIG90aGVyIHN0YXRpc3RpY2FsIHByb2plY3Rpb25zLCBoZWxwaW5nIGdvdmVybm1lbnRzIGluIHRoZWlyIGRlY2lzaW9uIG1ha2luZy4gVGhpcyBpbmRpY2F0b3IgaXMgbWVhc3VyZWQgaW4gdGVybXMgb2YgYW5udWFsIGdyb3d0aCByYXRlIGFuZCBpbiB0aG91c2FuZHMgb2YgcGVvcGxlLgoKICAtIENpdGF0aW9uOiBPRUNEICgyMDI0KSwgUG9wdWxhdGlvbiAoaW5kaWNhdG9yKS4gZG9pOiAxMC4xNzg3L2Q0MzRmODJiLWVuIChBY2Nlc3NlZCBvbiAyOCBKYW51YXJ5IDIwMjQpCgpgYGB7cn0KZGZfb2VjZF9wb3AgPC0gcmVhZF9jc3YoImRhdGEvRFBfTElWRV8yODAxMjAyNDA2NDAwMjk1Ny5jc3YiKQpkZl9vZWNkX3BvcApgYGAKCmBgYHtyfQpkZl9vZWNkX3BvcCB8PiBzZWxlY3QoLVZhbHVlKSB8PiBsYXBwbHkodW5pcXVlKQpgYGAKCmBgYHtyfQpkZl9wb3Bfc2hvcnQgPC0gZGZfb2VjZF9wb3AgfD4gZmlsdGVyKFNVQkpFQ1QgPT0gIlRPVCIpIHw+IHNlbGVjdChpc28zYyA9IExPQ0FUSU9OLCB5ZWFyID0gVElNRSwgcG9wID0gVmFsdWUpCmBgYAoKCiMjIyBDb21iaW5lIFRocmVlIERhdGFzZXRzIG9mIE9FQ0QKCkNoZWNrIHRoZSBkaWZmZXJlbmNlcyBvZiBjb3VudHJpZXMgaW4gZWFjaCBkYXRhc2V0cy4KCmBgYHtyfQpzZXRkaWZmKGRmX2Zwb3AkaXNvM2MsIGRmX2luJGlzbzNjKTsgc2V0ZGlmZihkZl9pbiRpc28zYyxkZl9mcG9wJGlzbzNjKQpzZXRkaWZmKGRmX2Zwb3AkaXNvM2MsIGRmX3BvcF9zaG9ydCRpc28zYyk7IHNldGRpZmYoZGZfaW4kaXNvM2MsIGRmX3BvcF9zaG9ydCRpc28zYykKYGBgCgoqICJIVU4iICJTVksiICJTVk4iICJHUkMiICJJU0wiICJUVVIiICJDSEwiICJMVkEiICJMVFUiIGFyZSBpbiBgZGZfZnBvcGAgYnV0IG5vdCBpbiBgZGZfaW5gLgoqICJBVVMiICJOWkwiICJJU1IiICJSVVMiIGFyZSBpbiBgZGZfaW5gIGJ1dCBub3QgaW4gYGRmX2Zwb3BgLgoqIGBkZl9wb3Bfc2hvcnRgIGNvbnRhaW5zIHRoZSBkYXRhIG9mIGNvdW50cmllcyBpbiBgZGZfaW5gIGFuZCBgZGZfZnBvcGAuCgpgYGB7cn0KZGZfZnBvcDIgPC0gZGZfZnBvcCB8PiBzZWxlY3QoaXNvM2MsIHllYXIsIGZvcmVpZ24pCmRmX29lY2RfZnBvcCA8LSBkZl9pbiB8PiBmdWxsX2pvaW4oZGZfZnBvcDIsIGJ5ID0gYygiaXNvM2MiLCAieWVhciIpKSB8PgogIGxlZnRfam9pbihkZl9wb3Bfc2hvcnQsIGJ5ID0gYygiaXNvM2MiLCAieWVhciIpKSB8PgogIG11dGF0ZShmb3JlaWduX3BvcCA9IHJvdW5kKHBvcCoxMDAwMCpmb3JlaWduKSwgLmFmdGVyID0gdmFsdWUpCmRmX29lY2RfZnBvcApgYGAKCmBgYHtyfQpkZl9vZWNkX2Zwb3AgfD4gZmlsdGVyKGNhdGVnb3J5ID09ICJUT1QiKSB8PiBkcm9wX25hKHZhbHVlLCBmb3JlaWduKSB8PgogIGZpbHRlcih2YWx1ZSA+MCwgZm9yZWlnbiA+MCkgfD4KICBnZ3Bsb3QoYWVzKHZhbHVlLCBmb3JlaWduX3BvcCkpICsgZ2VvbV9wb2ludChhZXMoY29sID0gaXNvM2MpKSArIHNjYWxlX3hfbG9nMTAoKSArIHNjYWxlX3lfbG9nMTAoKSArIGdlb21fc21vb3RoKGZvcm11bGEgPSAneX54JywgbWV0aG9kID0gImxtIiwgc2UgPSBGQUxTRSkKYGBgCgojIyBVTmRhdGEgLSBhIHdvcmxkIG9mIGluZm9ybWF0aW9uCgo8aHR0cHM6Ly9kYXRhLnVuLm9yZy8+CgpQb3B1bGFyIHN0YXRpc3RpY2FsIHRhYmxlcwoKRXhwbG9yZXIgLSBkYXRhbWFydHM6IDxodHRwOi8vZGF0YS51bi5vcmcvRXhwbG9yZXIuYXNweD4KCi0gICBEYXRhc2V0cywgU291cmNlcywgVG9waWNzCgojIyMgUG9wdWxhciBzdGF0aXN0aWNhbCB0YWJsZXMKCkNvcHkgdGhlIGxpbmsgb2YgSW50ZXJuYXRpb25hbCBNaWdyYW50cyBhbmQgUmVmdWdlZXMKCmBgYHtyfQp1bl9taWdyYW50c191cmwgPC0gImh0dHBzOi8vZGF0YS51bi5vcmcvX0RvY3MvU1lCL0NTVi9TWUI2Nl8zMjdfMjAyMzEwX0ludGVybmF0aW9uYWwlMjBNaWdyYW50cyUyMGFuZCUyMFJlZnVnZWVzLmNzdiIKZG93bmxvYWQuZmlsZSh1bl9taWdyYW50c191cmwsIGRlc3RmaWxlID0gImRhdGEvbWlncmFudHMuY3N2IikKYGBgCgpgYGB7cn0KZGZfdW5fbWlncmFudHMgPC0gcmVhZF9jc3YoImRhdGEvbWlncmFudHMuY3N2IikKZGZfdW5fbWlncmFudHMKYGBgCgpgYGB7cn0KZGZfdW5fbWlncmFudHMgPC0gcmVhZF9jc3YoImRhdGEvbWlncmFudHMuY3N2Iiwgc2tpcD0xKQpkZl91bl9taWdyYW50cwpgYGAKCmBgYHtyfQpzdHIoZGZfdW5fbWlncmFudHMpCmBgYAoKCmBgYHtyfQpkZl91bl9taWdyYW50cyB8PiBzdW1tYXJ5KCkKYGBgCgpgYGB7cn0KZGZfdW5fbWlncmFudHMgfD4gc2VsZWN0KFllYXIsU2VyaWVzKSB8PiBsYXBwbHkodW5pcXVlKQpgYGAKCmBgYHtyIGV2YWwgPSBGQUxTRX0KZGZfdW5fbWlncmFudHMgfD4gZGlzdGluY3QoYFJlZ2lvbi9Db3VudHJ5L0FyZWFgLCAuLi4yKQpgYGAKCmBgYHtyfQpsaWJyYXJ5KGNvdW50cnljb2RlKQpkZl91bl9taWdyYW50cyAlPiUgbXV0YXRlKGlzbzNjID0gY291bnRyeWNvZGUoYFJlZ2lvbi9Db3VudHJ5L0FyZWFgLCAidW4iLCAiaXNvM2MiKSwgLmFmdGVyID0gLi4uMikKYGBgCgpgYGB7cn0KZGZfdW5fbWlncmFudHMgfD4gbXV0YXRlKGlzbzNjID0gY291bnRyeWNvZGUoYFJlZ2lvbi9Db3VudHJ5L0FyZWFgLCAidW4iLCAiaXNvM2MiKSwgLmFmdGVyID0gLi4uMikgfD4gZmlsdGVyKGlzLm5hKGlzbzNjKSkgfD4gZGlzdGluY3QoLi4uMikKYGBgCgpgYGB7cn0Kd2RpY2FjaGUgPC0gcmVhZF9yZHMoImRhdGEvd2RpY2FjaGUucmRzIikKd2RpX2NvdW50cnlfZXh0cmEgPC0gd2RpY2FjaGUkY291bnRyeSB8PiBzZWxlY3QoaXNvM2MsIHJlZ2lvbiwgaW5jb21lLCBsZW5kaW5nKQpgYGAKCmBgYHtyIGV2YWw9RkFMU0V9CmRmX3VuX21pZ3JhbnRzX2V4dCA8LSBkZl91bl9taWdyYW50cyB8PgogIG11dGF0ZShpc28zYyA9IGNvdW50cnljb2RlKGBSZWdpb24vQ291bnRyeS9BcmVhYCwgInVuIiwgImlzbzNjIiksIC5hZnRlciA9IC4uLjIpIHw+CiAgZHJvcF9uYShpc28zYykgfD4gCiAgc2VsZWN0KGNvdW50cnkgPSAuLi4yLCBpc28zYywgeWVhciA9IFllYXIsIHNlcmllcyA9IFNlcmllcywgdmFsdWUgPSBWYWx1ZSwgZm9vdG5vdGVzID0gRm9vdG5vdGVzKSB8PgogIGxlZnRfam9pbih3ZGlfY291bnRyeV9leHRyYSwgYnkgPSAiaXNvM2MiKQpkZl91bl9taWdyYW50c19leHQKYGBgCgpgYGB7ciBlY2hvPUZBTFNFfQpkZl91bl9taWdyYW50c19leHQgPC0gZGZfdW5fbWlncmFudHMgJT4lIAogIG11dGF0ZShpc28zYyA9IGNvdW50cnljb2RlKGBSZWdpb24vQ291bnRyeS9BcmVhYCwgInVuIiwgImlzbzNjIiksIC5hZnRlciA9IC4uLjIpIHw+CiAgZHJvcF9uYShpc28zYykgfD4gCiAgc2VsZWN0KGNvdW50cnkgPSAuLi4yLCBpc28zYywgeWVhciA9IFllYXIsIFNlcmllcywgbWlncmFudHMgPSBWYWx1ZSwgRm9vdG5vdGVzKSB8PgogIGxlZnRfam9pbih3ZGlfY291bnRyeV9leHRyYSwgYnkgPSAiaXNvM2MiKQpkZl91bl9taWdyYW50c19leHQKYGBgCgpgYGB7cn0KZGZfdW5fbWlncmFudHNfZXh0JFNlcmllcyB8PiB1bmlxdWUoKQpgYGAKCmBgYHtyfQpkZl91bl9taWdyYW50c19leHRfcmV2IDwtIGRmX3VuX21pZ3JhbnRzX2V4dCB8PiBtdXRhdGUoc2VyID0gY2FzZV93aGVuKAogIFNlcmllcyA9PSAiSW50ZXJuYXRpb25hbCBtaWdyYW50IHN0b2NrOiBCb3RoIHNleGVzIChudW1iZXIpIiB+ICJtaWdyYW50IiwKICBTZXJpZXMgPT0gIkludGVybmF0aW9uYWwgbWlncmFudCBzdG9jazogQm90aCBzZXhlcyAoJSB0b3RhbCBwb3B1bGF0aW9uKSIgfiAibWlncmFudF9wZXJjZW50IiwKICBTZXJpZXMgPT0gIkludGVybmF0aW9uYWwgbWlncmFudCBzdG9jazogTWFsZSAoJSB0b3RhbCBQb3B1bGF0aW9uKSIgfiAibWlncmFudF9tYWxlIiwKICBTZXJpZXMgPT0gIkludGVybmF0aW9uYWwgbWlncmFudCBzdG9jazogRmVtYWxlICglIHRvdGFsIFBvcHVsYXRpb24pIiB+ICJtaWdyYW50X2ZlbWFsZSIsCiAgU2VyaWVzID09ICJUb3RhbCByZWZ1Z2VlcyBhbmQgcGVvcGxlIGluIHJlZnVnZWUtbGlrZSBzaXR1YXRpb25zIChudW1iZXIpIiB+ICJyZWZ1Z2VlIiwKICBTZXJpZXMgPT0gIkFzeWx1bSBzZWVrZXJzLCBpbmNsdWRpbmcgcGVuZGluZyBjYXNlcyAobnVtYmVyKSIgfiAiYXN5bHVtIiwKICBTZXJpZXMgPT0gIk90aGVyIG9mIGNvbmNlcm4gdG8gVU5IQ1IgKG51bWJlcikiICB+ICJvdGhlciIsCiAgU2VyaWVzID09ICJUb3RhbCBwb3B1bGF0aW9uIG9mIGNvbmNlcm4gdG8gVU5IQ1IgKG51bWJlcikiIH4gImNvbmNlcm4iLAogIFRSVUUgfiBTZXJpZXMpLCAuYmVmb3JlID0gU2VyaWVzKQpgYGAKCmBgYHtyfQpkZl91bl9taWdyYW50c19leHRfcmV2CmBgYAoKIyMjIEpvaW4gT0VDRCBEYXRhIHdpdGggVU4gRGF0YQoKYGBge3J9CmRmX29lY2RfdW4gPC0gZGZfb2VjZF9mcG9wIHw+IGxlZnRfam9pbihkZl91bl9taWdyYW50c19leHRfcmV2LCBieSA9IGMoImNvdW50cnkiLCAiaXNvM2MiLCAieWVhciIpKSB8PgogIHNlbGVjdChjb3VudHJ5LCBpc28zYywgY2F0ZWdvcnksIHllYXIsIHZhbHVlLCBmb3JlaWduX3BvcCwgZm9yZWlnbiwgcG9wLCBzZXIsIG1pZ3JhbnRzKQpkZl9vZWNkX3VuCmBgYAoKYGBge3J9CmRmX29lY2RfdW4gfD4gZmlsdGVyKGNvdW50cnkgPT0gIkphcGFuIikKYGBgCgpgYGB7cn0KZGZfb2VjZF91bl93aWRlIDwtIGRmX29lY2RfdW4gfD4gZHJvcF9uYSh2YWx1ZSwgbWlncmFudHMpIHw+IHBpdm90X3dpZGVyKG5hbWVzX2Zyb20gPSBjYXRlZ29yeSwgdmFsdWVzX2Zyb20gPSB2YWx1ZSkgIHw+CiAgcGl2b3Rfd2lkZXIobmFtZXNfZnJvbSA9IHNlciwgdmFsdWVzX2Zyb20gPSBtaWdyYW50cykKZGZfb2VjZF91bl93aWRlCmBgYAoKYGBge3J9CmRmX29lY2RfdW5fd2lkZSB8PgpgYGAKCgojIyMgRXhwZW5kaXR1cmUgb24gZWR1Y2F0aW9uYWwgaW5zdGl0dXRpb25zIHBlciBmdWxsLXRpbWUgZXF1aXZhbGVudCBzdHVkZW50CgpbW0xpbmtdKGh0dHBzOi8vZGF0YS1leHBsb3Jlci5vZWNkLm9yZy92aXM/ZnMlNUIwJTVEPVRvcGljJTJDMCU3Q0VkdWNhdGlvbiUyM0VEVSUyMyZwZz0wJmZjPVRvcGljJmJwPXRydWUmc25iPTM0JnZ3PXRiJmRmJTVCZHMlNUQ9ZHNEaXNzZW1pbmF0ZUZpbmFsRE1aJmRmJTVCaWQlNUQ9RFNEX0VBR19VT0VfRklOJTQwREZfVU9FX0lORElDX0ZJTl9QRVJTVFVEJmRmJTVCYWclNUQ9T0VDRC5FRFUuSU1FUCZkZiU1QnZzJTVEPTEuMCZwZD0yMDIwJTJDMjAyMCZkcT0uLklTQ0VEMTFfMSUyQklTQ0VEMTFfMiUyQklTQ0VEMTFfMyUyQklTQ0VEMTFfMzQlMkJJU0NFRDExXzM1JTJCSVNDRUQxMV80JTJCSVNDRUQxMV81JTJCSVNDRUQxMV81VDglMkJJU0NFRDExXzZUOCUyQklTQ0VEMTFfMVQ4Ll9ULklOU1RfRURVLkRJUl9FWFAuLiZseSU1QnJ3JTVEPVJFRl9BUkVBJmx5JTVCY2wlNUQ9RURVQ0FUSU9OX0xFViZ0byU1QlRJTUVfUEVSSU9EJTVEPXRydWUpXQoKVGFibGUgaW4gRXhjZWwsIEZpbHRlcmVkIGRhdGEgaW4gdGFibGVhdSB0ZXh0IChDU1YpLCBVbmZpbHRlcmVkIGRhdGEgaW4gdGFibGVhdSB0ZXh0IChDU1YpIDEzNi40TUIKCmBgYHtyIGV2YWwgPSBGQUxTRX0KdGVtcCA8LSByZWFkX2NzdigiLi4vLi4vLi4vYmlnZGF0YS9PRUNELkVEVS5JTUVQLERTRF9FQUdfVU9FX0ZJTkBERl9VT0VfSU5ESUNfRklOX1BFUlNUVUQsMS4wK2FsbC5jc3YiKQp0ZW1wCmBgYAoKYGBge3J9CmxpYnJhcnkocmVhZHhsKQpkZl9vZWNkX2VkIDwtIHJlYWRfZXhjZWwoImRhdGEvT0VDRC5FRFUuSU1FUCxEU0RfRUFHX1VPRV9GSU5AREZfVU9FX0lORElDX0ZJTl9QRVJTVFVELDEuMCxmaWx0ZXJlZCwyMDI0LTAxLTI0IDEwLTIyLTMxLnhsc3giKQpgYGAKCmBgYHtyfQpkZl9vZWNkX2VkCmBgYAoKYGBge3J9CmRmX29lY2RfZWQgPC0gcmVhZF9leGNlbCgiZGF0YS9PRUNELkVEVS5JTUVQLERTRF9FQUdfVU9FX0ZJTkBERl9VT0VfSU5ESUNfRklOX1BFUlNUVUQsMS4wLGZpbHRlcmVkLDIwMjQtMDEtMjQgMTAtMjItMzEueGxzeCIsIHNraXAgPSA2KQpkZl9vZWNkX2VkCmBgYAoKYGBge3J9CmNvbG5hbWVzKGRmX29lY2RfZWQpIApgYGAKCmBgYHtyfQpkZl9vZWNkX2VkX3Nob3J0IDwtIGRmX29lY2RfZWQgfD4gc2VsZWN0KDEsMyw0LDUsNiw5LDEwKSB8PiBkcm9wX25hKGBQcmltYXJ5IGVkdWNhdGlvbmApCmRmX29lY2RfZWRfc2hvcnQKYGBgCgpgYGB7cn0KZGZfb2VjZF9lZDIgPC0gcmVhZF9jc3YoImRhdGEvT0VDRC5FRFUuSU1FUCxEU0RfRUFHX1VPRV9GSU5AREZfVU9FX0lORElDX0ZJTl9QRVJTVFVELDEuMCsuLklTQ0VEMTFfMStJU0NFRDExXzIrSVNDRUQxMV8zK0lTQ0VEMTFfNCtJU0NFRDExXzUrSVNDRUQxMV81VDgrSVNDRUQxMV82VDgrSVNDRUQxMV8xVDguX1QuSU5TVF9FRFUuRElSX0VYUC4uLmNzdiIpCmRmX29lY2RfZWQyCmBgYAoKCiMjIFJlZmVyZW5jZXMKCi0gICBEYXRhIEFuYWx5c2lzIGZvciBSZXNlYXJjaGVycy4gW1tMaW5rXShodHRwczovL2ljdS1oc3V6dWtpLmdpdGh1Yi5pby9kYTRyLyldCgotICAgSC4gV2lja2hhbS4gKlIgZm9yIERhdGEgU2NpZW5jZSAoMmUpKi4gW1tMaW5rXShodHRwczovL3I0ZHMuaGFkbGV5Lm56KV3jg7tbW08nUkVJTExZXShodHRwczovL3d3dy5vcmVpbGx5LmNvbS9saWJyYXJ5L3ZpZXcvci1mb3ItZGF0YS85NzgxNDkyMDk3Mzk2LyldLgoKICAgIC0gICBEYXRhIHRyYW5zZm9ybWF0aW9uIFtbTGlua10oaHR0cHM6Ly9yNGRzLmhhZGxleS5uei9kYXRhLXRyYW5zZm9ybSldCgogICAgLSAgIERhdGEgdGlkeWluZyBbW0xpbmtdKGh0dHBzOi8vcjRkcy5oYWRsZXkubnovZGF0YS10aWR5KV0KCiAgICAtICAgRGF0YSBpbXBvcnQgW1tMaW5rXShodHRwczovL3I0ZHMuaGFkbGV5Lm56L2RhdGEtaW1wb3J0KV0KCiAgICAtICAgSW1wb3J0IFtbTGlua10oaHR0cHM6Ly9yNGRzLmhhZGxleS5uei9pbXBvcnQpXQoKLSAgIFBvc2l0IFJlY2lwZXPvvIhOZXcgZWRpdGlvbiBvZiBQb3NpdCBQcmltZXJz77yJOiBpbnRlcmFjdGl2ZSBleGVyY2lzZXMgW1tMaW5rXShodHRwczovL3Bvc2l0LmNsb3VkL2xlYXJuL3JlY2lwZXMpXQoKLSAgIENoZWF0IFNoZWV0LiBbW1NpdGUgTGlua10oaHR0cHM6Ly9yc3R1ZGlvLmdpdGh1Yi5pby9jaGVhdHNoZWV0cy8pXQoKICAgIC0gICBEYXRhIGltcG9ydCB3aXRoIHRoZSB0aWR5dmVyc2UgW1tMaW5rXShodHRwczovL3JzdHVkaW8uZ2l0aHViLmlvL2NoZWF0c2hlZXRzL2h0bWwvZGF0YS1pbXBvcnQuaHRtbCldCgogICAgLSAgIERhdGEgdHJhbnNmb3JtYXRpb24gd2l0aCBkcGx5ciBbW0xpbmtdKGh0dHBzOi8vcnN0dWRpby5naXRodWIuaW8vY2hlYXRzaGVldHMvaHRtbC9kYXRhLXRyYW5zZm9ybWF0aW9uLmh0bWwpXQoKLSAgIGRwbHlyOiBBIEdyYW1tYXIgb2YgRGF0YSBNYW5pcHVsYXRpb24gW1tMaW5rXShodHRwczovL0NSQU4uUi1wcm9qZWN0Lm9yZy9wYWNrYWdlPWRwbHlyKV0KCiAgICAtICAgVHdvLXRhYmxlIHZlcmJzIFtbTGlua10oaHR0cHM6Ly9jcmFuLnItcHJvamVjdC5vcmcvd2ViL3BhY2thZ2VzL2RwbHlyL3ZpZ25ldHRlcy90d28tdGFibGUuaHRtbCldCgotICAgTW9kZWwgU3VtbWFyeQoKICAgIC0gICByLXN0YXRpc3RpY3MuY28gYnkgU2VsdmEgUHJhYmhha2FyYW46CgogICAgICAgIC0gICA8aHR0cDovL3Itc3RhdGlzdGljcy5jby9MaW5lYXItUmVncmVzc2lvbi5odG1sPgoKICAgIC0gICBNZWFuaW5nIEJlaGluZCBFYWNoIFNlY3Rpb24gb2YgU3VtbWFyeSgpCgogICAgICAgIC0gICA8aHR0cHM6Ly93d3cubGVhcm5ieW1hcmtldGluZy5jb20vdHV0b3JpYWxzL2V4cGxhaW5pbmctdGhlLWxtLXN1bW1hcnktaW4tci8+CgotICAgc3dpcmw6IGBpbnN0YWxsLnBhY2thZ2VzKCJzd2lybCIpYCBgbGlicmF5KHN3aXJsKWAsIGFuZCBgc3dpcmwoKWAgYWZ0ZXIgYHJtKGxpc3Q9bHMoKSlgCg==